package com.lzh.chatnote.user.service;


import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.lzh.chatnote.common.constant.MQConstant;
import com.lzh.chatnote.common.constant.RedisKey;
import com.lzh.chatnote.common.domain.dto.LoginMessageDTO;
import com.lzh.chatnote.common.domain.dto.ScanLoginDTO;
import com.lzh.chatnote.common.mqProducer.MQProducer;
import com.lzh.chatnote.common.utils.RedisUtils;
import com.lzh.chatnote.user.dao.UserDao;
import com.lzh.chatnote.user.domain.entity.User;
import com.lzh.chatnote.user.service.adapter.TextBuilder;
import com.lzh.chatnote.user.service.adapter.UserAdapter;
import com.lzh.chatnote.webSocket.enums.LoginTypeEnum;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.URLEncoder;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class WxMsgService {

    @Resource
    private UserDao userDao;
    @Resource
    private UserService userService;
    @Resource
    private MQProducer mqProducer;


    private static final String URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";

    /**
     * 微信扫码事情触发逻辑
     *
     * @param wxMpService    微信服务 封装出发点事件报文等信息
     * @param wxMpXmlMessage 微信消息 这里封装了微信登录凭证等信息
     * @return
     */
    public WxMpXmlOutMessage scan(WxMpService wxMpService, WxMpXmlMessage wxMpXmlMessage) {
        //获取当前关注的用户ID（微信的唯一标识）
        String openid = wxMpXmlMessage.getFromUser();
        //获取微信扫码的验证码
        Integer loginCode = Integer.parseInt(getEventKey(wxMpXmlMessage));
        //根据微信唯一标识获取用户
        User user = userDao.getUserByOpenId(openid);
        if (Objects.nonNull(user)) {
            //当前用户已经注册了，不需要用户确认登录，尝试直接进行用户登录逻辑
            //todo
            mqProducer.sendMsg(MQConstant.LOGIN_MSG_TOPIC, new LoginMessageDTO(user.getId(), loginCode));
            return null;
        }
        //用户未登录过
        //构建注册用户
        user = User.builder()
                .openId(openid)
                .username("")
                .password("")
                .registerType(LoginTypeEnum.of("weixin").getValue())
                .build();
        userService.registerUser(user);

        //在redis里保存 openid和验证码的映射关系，用于用户授权后进行用户登录逻辑
        //用户授权回调接口只会传递openid
        RedisUtils.set(RedisKey.getKey(RedisKey.USER_OPENID, openid), loginCode, 30, TimeUnit.MINUTES);

        //发送给前段端让用户进行进行授权
        mqProducer.sendMsg(MQConstant.SCAN_MSG_TOPIC, new ScanLoginDTO(loginCode));

        //用户确认登录链接
        String skipUrl = String.format(URL, wxMpService.getWxMpConfigStorage().getAppId(), URLEncoder.encode("https://7397yz4kl098.vicp.fun/wx/public/callBack"));
        WxMpXmlOutMessage.TEXT().build();
        return new TextBuilder().build("请点击链接授权：<a href=\"" + skipUrl + "\">登录</a>", wxMpXmlMessage, wxMpService);
    }


    private String getEventKey(WxMpXmlMessage wxMpXmlMessage) {
        return wxMpXmlMessage.getEventKey().replace("qrscene_", "");
    }


    public WxMpXmlOutMessage textResponse(WxMpService wxMpService, WxMpXmlMessage wxMpXmlMessage) {
        String fromUser = wxMpXmlMessage.getFromUser();
        //System.out.println("fromUser " + fromUser);
        //return new TextBuilder().build("<a>点击</a>",wxMpXmlMessage,wxMpService);
        String skipUrl = String.format(URL, wxMpService.getWxMpConfigStorage().getAppId(), URLEncoder.encode("https://f5w4694351.goho.co/wx/public/callBack"));
        WxMpXmlOutMessage.TEXT().build();
        return new TextBuilder().build("请点击链接授权：<a href=\"" + skipUrl + "\">登录</a>", wxMpXmlMessage, wxMpService);
    }

    public void authorize(WxOAuth2UserInfo userInfo) {
        User user = userDao.getUserByOpenId(userInfo.getOpenid());
        if (StrUtil.isBlank(user.getAvatar()) || StrUtil.isBlank(user.getUsername())) {
            //填充微信授权的用户信息
            fillUserInfo(userInfo, user);
        }
        //通过扫码获取的openid和code存在redis里了，获取登录码
        Integer code = RedisUtils.get(RedisKey.getKey(RedisKey.USER_OPENID, user.getOpenId()), Integer.class);
        //发送已经授权的mq，进行登录
        mqProducer.sendMsg(MQConstant.LOGIN_MSG_TOPIC, new LoginMessageDTO(user.getId(), code));
    }


    public void fillUserInfo(WxOAuth2UserInfo userInfo, User user) {
        User fillUserInfo = UserAdapter.fillUser(userInfo, user);
        //防止名字冲突
        for (int i = 0; i < 6; i++) {
            try {
                userDao.updateById(fillUserInfo);
            } catch (DuplicateKeyException e) {
                log.info("用户名字重复:{},用户信息为:{}", userInfo.getOpenid(), userInfo);
            } catch (Exception e) {
                log.error("保存用户信息失败{}", userInfo);
                throw new RuntimeException(e);
            }
            fillUserInfo.setName("名字重置" + RandomUtil.randomInt(100000));
        }
    }
}
